package com.backend.controllers;

import com.backend.models.*;
import com.backend.struts.*;
import com.backend.utils.CommonStringUtils;
import com.backend.utils.UserManageUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.Gson;
import com.qiniu.util.StringUtils;
import io.ebean.Ebean;
import io.ebean.Expr;
import io.ebean.ExpressionList;
import org.antlr.v4.runtime.misc.Utils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Controller
public class WebViewController {
    @RequestMapping(value = "/app/webview_product_detail/", method = RequestMethod.GET)
    public ModelAndView showProductDetail(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer productId = params.getIntParam("product_id", 0);
        Product product = Product.find.byId(productId);
        if (product != null) {
            product.setPopularity(product.popularity + 2);
            ModelAndView modelAndView = new ModelAndView("app_product/product_detail");
            List<ImageStorge> imageStorgeList = ImageStorge.search().eq("boomId", product.id).eq("category", ImageStorge.IMAGE_TYPE.PRODUCT)
                    .eq("deleted", false).orderBy("orderNum asc").findList();
            JsonNode userDict = UserManageUtils.getUserInfoById(product.userId);
            List<ProductComment> comments = ProductComment.search().eq("product", product).eq("deleted", false).findList();
            Integer commentNum = comments.size();
            List<String> userIds = comments.stream().map(Comment -> CommonStringUtils.safeString(Comment.userId)).distinct().collect(Collectors.toList());
            String userIdStr = Utils.join(userIds.iterator(), ",");
            String usersInfo = UserManageUtils.getGetUsersInfoByIds(userIdStr);
            Map<Integer, Map<String, String>> usersInfoMap = new Gson().fromJson(usersInfo, Map.class);
            List<CommentObj> commentObjs = new ArrayList<>();
            comments.stream().filter(comment1 -> comment1.reComment == null).sorted(Comparator.comparing(o -> o.createTime)).forEach(comment1 -> {
                commentObjs.add(new CommentObj(comment1, comments, usersInfoMap));
            });
            product.save();
            modelAndView.addObject("product", product);
            modelAndView.addObject("images", imageStorgeList);
            modelAndView.addObject("user_info", userDict);
            modelAndView.addObject("users_info", usersInfoMap);
            modelAndView.addObject("comments", commentObjs);
            modelAndView.addObject("comment_num", commentNum);
            return modelAndView;
        } else {
            ModelAndView modelAndView = new ModelAndView("error/open_failure");
            return modelAndView;
        }
    }

    @RequestMapping(value = "/app/show_modify_or_add_delivery_address/", method = RequestMethod.GET)
    public ModelAndView showModifyOrAddDeliveryAddress(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        Integer deliveryAddressId = params.getIntParam("delivery_address_id", 0);
        DeliveryAddress deliveryAddress = DeliveryAddress.find.byId(deliveryAddressId);
        ModelAndView modelAndView = new ModelAndView("app_product/delivery_address_add");
        modelAndView.addObject("delivery_address", deliveryAddress);
        modelAndView.addObject("user_id", CommonStringUtils.safeString(userId));
        return modelAndView;
    }

    @RequestMapping(value = "/app/modify_or_add_delivery_address/", method = RequestMethod.POST)
    @ResponseBody
    public String addOrModifyDeliveryAddress(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        String name = params.getParam("name");
        String mobile = params.getParam("mobile");
        if (userId == 0 || StringUtils.isNullOrEmpty(name) || StringUtils.isNullOrEmpty(mobile)) {
            return "error";
        }
        Integer deliveryAddressId = params.getIntParam("delivery_address_id", 0);
        String province = params.getParam("province");
        String city = params.getParam("city");
        String schoolName = params.getParam("school_name");
        String postCode = params.getParam("post_code");
        Boolean isDefault = params.getBooleanParam("is_default", false);
        String fullAddress = params.getParam("full_address");
        DeliveryAddress address = DeliveryAddress.find.byId(deliveryAddressId);
        if (address == null) {
            address = new DeliveryAddress();
            address.setUserId(userId);
        }
        address.setProvince(province);
        address.setCity(city);
        address.setSchoolName(schoolName);
        address.setFullAddress(fullAddress);
        address.setPostCode(postCode);
        address.setName(name);
        address.setMobile(mobile);
        address.setLastModifyTime(new Date());
        if (isDefault) {
            DeliveryAddress deliveryAddress1 = DeliveryAddress.search().eq("userId", userId)
                    .eq("isDefault", true).eq("deleted", false).ne("id", deliveryAddressId).findOne();
            if (deliveryAddress1 != null) {
                deliveryAddress1.setIsDefault(false);
                deliveryAddress1.save();
            }
        }
        address.setIsDefault(isDefault);
        address.save();
        return "success";
    }

    @RequestMapping(value = "/app/delete_delivery_address/", method = RequestMethod.POST)
    @ResponseBody
    public String deleteDeliveryAddress(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer deliveryAddressId = params.getIntParam("delivery_address_id", 0);
        DeliveryAddress deliveryAddress = DeliveryAddress.find.byId(deliveryAddressId);
        if (deliveryAddress == null) {
            return "invalid address";
        }
        deliveryAddress.setLastModifyTime(new Date());
        deliveryAddress.setDeleted(true);
        deliveryAddress.save();
        return "success";
    }

    @RequestMapping(value = "/app/show_coollected_product/", method = RequestMethod.GET)
    public ModelAndView showCollectedProducts(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        List<ProductCollect> productCollects = ProductCollect.search().eq("userId", userId).eq("isCollected", true).findList();
        List<Integer> userIds = Product.search().in("id", productCollects.stream().map(productCollect -> productCollect.product.id).collect(Collectors.toList()))
                .findList().stream().map(product -> product.userId).collect(Collectors.toList());
        ModelAndView modelAndView = new ModelAndView("app_product/show_collect_product");
        String userIdStr = Utils.join(userIds.iterator(), ",");
        String usersInfo = UserManageUtils.getGetUsersInfoByIds(userIdStr);
        Map<String, Map<String, String>> usersInfoMap = new Gson().fromJson(usersInfo, Map.class);
        modelAndView.addObject("productCollects", productCollects);
        modelAndView.addObject("usersMap", usersInfoMap);
        modelAndView.addObject("user_id", userId);
        return modelAndView;
    }

    @RequestMapping(value = "/app/show_orders/", method = RequestMethod.GET)
    public ModelAndView showOrders(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        String pageTitle = params.getParam("page_title", "所有订单");
        ModelAndView modelAndView;
        modelAndView = new ModelAndView("app_product/show_orders");
        modelAndView.addObject("user_id", userId.toString());
        modelAndView.addObject("page_title", pageTitle);
        return modelAndView;
    }

    @RequestMapping(value = "/app/get_orders_data/", method = RequestMethod.POST)
    @ResponseBody
    public String getOrderDatas(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        String type = params.getParam("type", "all");
        Integer pageIndex = params.getIntParam("page", 1);
        Integer pageSize = params.getIntParam("pagesize", 10);
        ExpressionList<Order> orderExpressionList = Order.search().or(Expr.eq("userId", userId),Expr.eq("salerId",userId)).eq("deleted", false);
        if (!"all".equals(type)) {
            Order.ORDER_STATUS orderStatus = Order.ORDER_STATUS.getObj(type);
            Order.SALE_STATUS saleStatus = Order.SALE_STATUS.getObj(type);
            orderExpressionList.or(Expr.eq("status", orderStatus), Expr.eq("saleStatus", saleStatus));
        }
        List<Order> orders = orderExpressionList.orderBy("createTime desc").setFirstRow((pageIndex - 1) * pageSize).setMaxRows(pageIndex * pageSize).findList();
        Map<Integer, Product> productMap = Product.search().in("id", orders.stream().map(order -> order.product.id).collect(Collectors.toList())).findMap();
        List<OrderObj> orderObjs = new ArrayList<>();
        for (Order order : orders) {
            OrderObj orderObj = new OrderObj(order);
            ProductObj productObj = new ProductObj(productMap.get(order.product.id));
            orderObj.setProduct(productObj);
            orderObjs.add(orderObj);
        }
        return new Gson().toJson(orderObjs);
    }

    @RequestMapping(value = "/app/show_order_detail/", method = RequestMethod.GET)
    public ModelAndView showOrderDetail(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer orderId = params.getIntParam("order_id", 0);
        Integer userId = params.getIntParam("user_id",0);
        Order order = Order.find.byId(orderId);
        ModelAndView modelAndView;
        if (order == null || order.product == null) {
            modelAndView = new ModelAndView("error/open_failure");
            return modelAndView;
        }
        OrderObj orderObj = new OrderObj(order);
        Product product = Product.find.byId(order.product.id);
        ProductObj productObj = new ProductObj(product);
        orderObj.setProduct(productObj);
        String usersInfo = UserManageUtils.getGetUsersInfoByIds(product.userId.toString());
        Map<String, Map<String, String>> usersInfoMap = new Gson().fromJson(usersInfo, Map.class);
        UserInfo userInfo = new UserInfo(usersInfoMap.get(product.userId.toString()));
        orderObj.setUser(userInfo);
        modelAndView = new ModelAndView("app_product/order_detail");
        modelAndView.addObject("order_id", orderId);
        modelAndView.addObject("user_id",userId);
        modelAndView.addObject("order_obj",orderObj);
        modelAndView.addObject("order",order);
        return modelAndView;
    }

    @RequestMapping(value = "/app/show_my_publishs/", method = RequestMethod.GET)
    public ModelAndView showMyPublishProducts(HttpServletRequest request){
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id",0);
        ModelAndView modelAndView = new ModelAndView("app_product/my_publish");
        modelAndView.addObject("user_id",userId);
        return modelAndView;
    }

    @RequestMapping(value = "/app/get_publish_datas/", method = RequestMethod.POST)
    @ResponseBody
    public String getPublishDatas(HttpServletRequest request){
        HttpParams params = new HttpParams(request);
        Integer page = params.getIntParam("page",1);
        Integer pageSize = params.getIntParam("pagesize",10);
        Integer userId = params.getIntParam("user_id",0);
        List<Product> products = Product.search().eq("userId",userId).orderBy("createTime desc").setFirstRow((page - 1) * pageSize).setMaxRows(page * pageSize).findList();
        List<ProductObj> productObjs = products.stream().map(product -> new ProductObj(product)).collect(Collectors.toList());
        return new Gson().toJson(productObjs);
    }

    @RequestMapping(value = "/app/sure_took_goods/", method = RequestMethod.POST)
    @ResponseBody
    public String sureTookGoods(HttpServletRequest request){
        HttpParams params = new HttpParams(request);
        Integer orderId = params.getIntParam("order_id",0);
        Order order = Order.find.byId(orderId);
        String msg = "error";
        if(order == null){
            return msg;
        }
        Ebean.beginTransaction();
        try{
            order.setSaleStatus(Order.SALE_STATUS.finished);
            order.setStatus(Order.ORDER_STATUS.finished);
            order.product.setStatus(GlobalDefine.PRODUCT_STATUS.saled);
            order.product.save();
            order.save();
            Ebean.commitTransaction();
            msg = "success";
        }catch (Exception e){
            Ebean.rollbackTransaction();
        }finally {
            Ebean.endTransaction();
        }
        return msg;
    }

    @RequestMapping(value = "/app/sure_send_product/", method = RequestMethod.POST)
    @ResponseBody
    public String sureSendProduct(HttpServletRequest request){
        HttpParams params = new HttpParams(request);
        Integer orderId = params.getIntParam("order_id",0);
        Order order = Order.find.byId(orderId);
        String msg = "error";
        if(order == null){
            return msg;
        }
        Ebean.beginTransaction();
        try{
            order.setSaleStatus(Order.SALE_STATUS.sended);
            order.setStatus(Order.ORDER_STATUS.sended);
            order.save();
            Ebean.commitTransaction();
            msg = "success";
        }catch (Exception e){
            Ebean.rollbackTransaction();
        }finally {
            Ebean.endTransaction();
        }
        return msg;
    }

    @RequestMapping(value = "/app/delete_product_by_id/", method = RequestMethod.POST)
    @ResponseBody
    public String deleteProduct(HttpServletRequest request){
        HttpParams params = new HttpParams(request);
        Integer productId = params.getIntParam("product_id",0);
        Product product = Product.find.byId(productId);
        String msg = "error";
        if(product == null || !GlobalDefine.PRODUCT_STATUS.insale.equals(product.status)){
            return msg;
        }
        Ebean.beginTransaction();
        try{
            product.setStatus(GlobalDefine.PRODUCT_STATUS.deleted);
            product.save();
            Ebean.commitTransaction();
            msg = "success";
        }catch (Exception e){
            Ebean.rollbackTransaction();
        }finally {
            Ebean.endTransaction();
        }
        return msg;
    }
}
